﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SQLite;
using System.IO;
using System.Collections.ObjectModel;

namespace MOJsdk
{
    public class MojMovieFileCollection : ObservableCollection<MojMovieFile>
    {
        #region Inicialization
        public MojMovieFileCollection(IEnumerable<MojMovieFile> EnumerableCollection)
            : base(EnumerableCollection)
        {

        }
        public MojMovieFileCollection(string MovieCode)
        {
            FileDataBaseInterop files = MojHost.GetHost.MoJSystem.FilesInterop;
            foreach (var v in files.Table<MoJBasicFile>().Where(z => z.MovieCode == MovieCode && z.FileType == 0))
                Add(new MojMovieFile(v));
        }
        #endregion

        public long ByteSize
        {
            get
            {
                long size = 0;

                foreach (var v in this)
                    size += v.FileInfo.Length;

                return size;
            }
        }
        public TimeSpan TotalDuration
        {
            get
            {
                TimeSpan dur = new TimeSpan(0, 0, 0);

                foreach (var v in this)
                    dur.Add(v.MovieInfo.Duration);

                return dur;
            }
        }
        public bool IsAvaible
        {
            get
            {
                foreach (var v in this)
                    if (!v.IsAvaible)
                        return false;

                return true;
            }
        }
    }
    public class MojSubtitleFileCollection : ObservableCollection<MojSubtitleFile>
    {
        #region Inicialization
        public MojSubtitleFileCollection(IEnumerable<MojSubtitleFile> EnumerableCollection)
            : base(EnumerableCollection)
        {

        }
        public MojSubtitleFileCollection(string MovieCode)
        {
            FileDataBaseInterop files = MojHost.GetHost.MoJSystem.FilesInterop;
            foreach (var v in files.Table<MoJBasicFile>().Where(z => z.MovieCode == MovieCode && z.FileType == 1))
                Add(new MojSubtitleFile(v));
        }
        #endregion

        public long ByteSize
        {
            get
            {
                long size = 0;

                foreach (var v in this)
                    size += v.FileInfo.Length;

                return size;
            }
        }
        public List<string> AvaibleLanguage
        {
            get
            {
                return new List<string>(this.Select(z => z.SubtileLanguageName));
            }
        }
        public bool HasSubtitle(string Language)
        {
            return AvaibleLanguage.Contains(Language);
        }
        public bool IsAvaible
        {
            get
            {
                foreach (var v in this)
                    if (!v.IsAvaible)
                        return false;

                return true;
            }
        }
    }
    public class MojImageFileCollection : ObservableCollection<MojImageFile>
    {
        #region Inicialization
        public MojImageFileCollection(IEnumerable<MojImageFile> EnumerableCollection)
            : base(EnumerableCollection)
        {

        }
        public MojImageFileCollection(string MovieCode)
        {
            FileDataBaseInterop files = MojHost.GetHost.MoJSystem.FilesInterop;
            foreach (var v in files.Table<MoJBasicFile>().Where(z => z.MovieCode == MovieCode && (z.FileType == 2 || z.FileType == 3)))
                Add(new MojImageFile(v));
        }
        #endregion

        public long ByteSize
        {
            get
            {
                long size = 0;

                foreach (var v in this)
                    size += v.FileInfo.Length;

                return size;
            }
        }
        public List<MojImageFile> CoverImages
        { get { return new List<MojImageFile>(this.Where(z=>z.ImageType == MOJFileTypes.CoverFile)); } }
        public List<MojImageFile> BackDropImages
        { get { return new List<MojImageFile>(this.Where(z => z.ImageType == MOJFileTypes.BackDropFile)); } }
        public bool IsAvaible
        {
            get
            {
                foreach (var v in this)
                    if (!v.IsAvaible)
                        return false;

                return true;
            }
        }
    }

    public class MojImageFile : MoJBasicFile, LogicalClass
    {
        #region Inicialization
        public MojImageFile(MoJBasicFile File)
        {
            SetBasicFile(File);
        }
        public MojImageFile(int FileId)
        {
            MojSystem system = MojHost.GetHost.MoJSystem;
            if (system.FilesInterop.FileExist(FileId))
                SetBasicFile(system.FilesInterop.GetFile(FileId));
            else
                throw new Exception("Invalid FileId");
        }
        private void SetBasicFile(MoJBasicFile file)
        {
            if (file.FileType != 2 && file.FileType != 3)
                throw new Exception("Invalid file type");

            FilePath = file.FilePath;
            FileID = file.FileID;
            FileIndex = file.FileIndex;
            FileType = file.FileType;
            OriginalName = file.OriginalName;
            DiskID = file.DiskID;
            MovieCode = file.MovieCode;
            Language = file.Language;
        }
        #endregion

        public bool IsAvaible
        {
            get
            {
                return MojHost.GetHost.MoJSystem.DrivePool.ContainsKey(this.DiskID);
            }
        }
        public string FileFullPath
        {
            get 
            {
                if(IsAvaible)
                    return MojHost.GetHost.MoJSystem.DrivePool[DiskID] + FilePath.Substring(1);

                return null;
            }
        }
        public MOJFileTypes ImageType
        { get { return (MOJFileTypes)FileType; } }
        public FileInfo FileInfo
        { get { return new FileInfo(FileFullPath); } }

        public bool TestStatment(LogicStatment statment)
        {
            string method = statment.BuildClass("MojImageFile THIS = (MojImageFile)elem\n");
            return ScriptInterop.RunLogicMethod(method, this);
        }
    }
    public class MojSubtitleFile : MoJBasicFile, LogicalClass
    {
        #region Inicialization
        public MojSubtitleFile(MoJBasicFile File)
        {
            SetBasicFile(File);
        }
        public MojSubtitleFile(int FileId)
        {
            MojSystem system = MojHost.GetHost.MoJSystem;
            if (system.FilesInterop.FileExist(FileId))
                SetBasicFile(system.FilesInterop.GetFile(FileId));
            else
                throw new Exception("Invalid FileId");
        }
        private void SetBasicFile(MoJBasicFile file)
        {
            if (file.FileType != 1)
                throw new Exception("Invalid file type");

            FilePath = file.FilePath;
            FileID = file.FileID;
            FileIndex = file.FileIndex;
            FileType = file.FileType;
            OriginalName = file.OriginalName;
            DiskID = file.DiskID;
            MovieCode = file.MovieCode;
            Language = file.Language;
        }
        #endregion

        public bool IsAvaible
        {
            get
            {
                return MojHost.GetHost.MoJSystem.DrivePool.ContainsKey(this.DiskID);
            }
        }
        public string FileFullPath
        {
            get
            {
                if (IsAvaible)
                    return MojHost.GetHost.MoJSystem.DrivePool[DiskID] + FilePath.Substring(1);

                return null;
            }
        }
        public FileInfo FileInfo
        { get { return new FileInfo(FileFullPath); } }

        public string SubtileLanguageName
        { get { return MojHost.GetHost.MoJSystem.LanguagePool[Language]; } }
        public bool TestStatment(LogicStatment statment)
        {
            string method = statment.BuildClass("MojSubtitleFile THIS = (MojSubtitleFile)elem\n");
            return ScriptInterop.RunLogicMethod(method, this);
        }
    }
    public class MojMovieFile : MoJBasicFile, LogicalClass
    {
        #region Inicialization
        public MojMovieFile(MoJBasicFile File)
        {
            SetBasicFile(File);
        }
        public MojMovieFile(int FileId)
        {
            MojSystem system = MojHost.GetHost.MoJSystem;
            if (system.FilesInterop.FileExist(FileId))
                SetBasicFile(system.FilesInterop.GetFile(FileId));
            else
                throw new Exception("Invalid FileId");
        }
        private void SetBasicFile(MoJBasicFile file)
        {
            if (file.FileType != 0)
                throw new Exception("Invalid file type");

            FilePath = file.FilePath;
            FileID = file.FileID;
            FileIndex = file.FileIndex;
            FileType = file.FileType;
            OriginalName = file.OriginalName;
            DiskID = file.DiskID;
            MovieCode = file.MovieCode;
            Language = file.Language;
        }
        #endregion

        public bool IsAvaible
        {
            get
            {
                return MojHost.GetHost.MoJSystem.DrivePool.ContainsKey(this.DiskID);
            }
        }
        public string FileFullPath
        {
            get
            {
                if (IsAvaible)
                    return MojHost.GetHost.MoJSystem.DrivePool[DiskID] + FilePath.Substring(1);

                return null;
            }
        }
        public FileInfo FileInfo
        { 
            get 
            {
                return new FileInfo(FileFullPath);
            } 
        }
        public MovieFileInfo MovieInfo
        { get { return new MovieFileInfo(FileFullPath); } }


        public bool TestStatment(LogicStatment statment)
        {
            string method = statment.BuildClass("MojMovieFile THIS = (MojMovieFile)elem\n");
            return ScriptInterop.RunLogicMethod(method, this);
        }
    }

    public class MoJBasicFile : IEquatable<MoJBasicFile>
    {
        public MoJBasicFile() { }
        public MoJBasicFile(string filePath, int index, MOJFileTypes type, string movieCode,  string language = "")
        {
            OriginalName = Path.GetFileNameWithoutExtension(FilePath);
            DiskID = TOOLS.GetDriveID(filePath);
            FileIndex = index;
            FileType = (int)type;
            MovieCode = movieCode;
            Language = Language;
            FilePath = filePath;
        }

        [PrimaryKey, AutoIncrement]
        public int FileID
        { get; set; }

        public string OriginalName
        { get; set; }
        public string DiskID
        { get; set; }
        public int FileIndex
        { get; set; }
        public int FileType
        { get; set; }
        public string MovieCode
        { get; set; }
        public string Language
        { get; set; }

        [Unique]
        public string FilePath
        { get; set; }

        //IEquatable<MoJBasicFile>
        public bool Equals(MoJBasicFile obj)
        {
            return FileID == obj.FileID;
        }

        //Explicit Conversion
        public static explicit operator MoJBasicFile(int fileID)
        {
            return new MoJBasicFile() { FileID = fileID };
        }
    }
    public enum MOJFileTypes
    {
        MovieFile = 0,
        SubtitleFile = 1,
        CoverFile = 2,
        BackDropFile = 3,
    }
}
